﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using UFIDA.U9.ISV.Item;
using UFSoft.UBF.Business;

namespace ufida.u9.ait.openapi.utils
{
    class DTOUtils
    {
        static bool IsValid = true;

        static DTOUtils()
        {
            IsValid = U9Utils.IsValid();
        }

        public static List<object> DTOListPropCopy(List<object> fromdtos,Type toType)
        {
            if(fromdtos == null)
                return null; 

            List<object> todtos = new List<object>();
            foreach(object fromdto in fromdtos)
            {
                object todto = Activator.CreateInstance(toType);
                DTOPropCopy(fromdto,todto);
                todtos.Add(todto);
            }
            return todtos;
        }

        public static void DTOPropCopy(object fromdto, object todto)
        {
            if (!IsValid)
            {
                return;
            }

            PropertyInfo[] propertyInfos = fromdto.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);

            //循环每个原dto属性
            foreach (var prop in propertyInfos)
            {
                try
                {
                    //该字段父类也存在,获取时会报错
                    if (prop.Name.Equals("SysState"))
                        continue;

                    //判断原属性是否有值
                    if (prop.GetValue(fromdto) != null)
                    {
                        //目标属性
                        PropertyInfo toprop = todto.GetType().GetProperty(prop.Name);
                        //判断目标属性是否存在
                        if (toprop == null)
                        {
                            //不存在直接跳过
                            continue;
                        }
                        if (toprop.PropertyType.IsSubclassOf(typeof(DataTransObjectBase)))
                        {
                            //如果目标dto属性类型是dto类型,递归处理下层属性
                            object todto1 = Activator.CreateInstance(toprop.PropertyType);
                            DTOPropCopy(prop.GetValue(fromdto), todto1);
                            toprop.SetValue(todto, todto1);
                        }
                        else if (toprop.PropertyType.IsGenericType && toprop.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
                        {
                            //如果目标dto属性类型是list<dto>类型,循环递归
                            if (!(prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(List<>)))
                                throw new Exception($"属性{prop.Name}必须是集合类型");

                            //获取list<>中的数据类型
                            Type fromType = prop.PropertyType.GetGenericArguments()[0];
                            Type fromlistType = prop.PropertyType;
                            Type toType = toprop.PropertyType.GetGenericArguments()[0];
                            Type tolistType = toprop.PropertyType;
                            //获取原属性list数据
                            IList flist = (IList)prop.GetValue(fromdto);
                            List<object> flist1 = new List<object>();
                            foreach (object item in flist)
                            {
                                flist1.Add(item);
                            }
                            //转换为目标属性list数据
                            List<object> tolist = DTOListPropCopy(flist1, toType);
                            IList tolist1 = (IList)Activator.CreateInstance(tolistType);
                            foreach (object item in tolist)
                            {
                                tolist1.Add(Convert.ChangeType(item, toType));
                            }
                            toprop.SetValue(todto, tolist1);
                        }
                        else if (toprop.PropertyType == typeof(DateTime))
                        {
                            //日期类型处理
                            if (prop.GetValue(fromdto) != null)
                            {
                                DateTime date = DateTime.Parse(prop.GetValue(fromdto).ToString());
                                toprop.SetValue(todto, date);
                            }
                        }
                        else
                        {
                            //其他类型处理
                            toprop.SetValue(todto, prop.GetValue(fromdto));
                        }
                    }
                }
                catch(Exception ex)
                {
                    throw new Exception($"属性名称:[{prop.Name}],值:[{prop.GetValue(fromdto)}]处理异常", ex);
                }
            }
        }
    }
}
